using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace BF
{
    /// <summary>
    /// 计时器执行器
    /// </summary>
    internal sealed class TimerExecutor : MonoSingleton<TimerExecutor>
    {
        protected override bool isDontDestroy => true;

        private readonly List<Timer> _timers = new List<Timer>();

        private readonly Dictionary<string, Timer> _timersDic = new Dictionary<string, Timer>();

        private readonly List<Timer> _tempTimers = new List<Timer>();

        private bool _isAllPause = false;

        private void Update()
        {
            if (_isAllPause)
            {
                return;
            }

            float deltaTime = Time.deltaTime;
            deltaTime *= Timer.timeScale;

            _tempTimers.Clear();
            _tempTimers.AddRange(_timers);
            foreach (Timer timer in _tempTimers)
            {
                TimerOnUpdate(timer, deltaTime);
            }

            _tempTimers.Clear();
            _tempTimers.AddRange(_timersDic.Values);
            foreach (Timer timer in _tempTimers)
            {
                TimerOnUpdate(timer, deltaTime);
            }
        }

        private void TimerOnUpdate(Timer timer, float deltaTime)
        {
#if UNITY_EDITOR
            timer.OnUpdate(deltaTime);
#else
            try
            {
                timer.OnUpdate(deltaTime);
            }
            catch (Exception e)
            {
                Debug.LogError($"[Timer][ExecutorError][{timer.key}], {e}");
            }
#endif
        }

        internal void Execute(Timer timer)
        {
            if (string.IsNullOrEmpty(timer.key))
            {
                _timers.Add(timer);
            }
            else
            {
                if (_timersDic.ContainsKey(timer.key))
                {
                    _timersDic[timer.key].Stop();
                    _timersDic.Remove(timer.key);
                }
                _timersDic.Add(timer.key, timer);
            }
        }

        internal bool Remove(Timer timer)
        {
            if (string.IsNullOrEmpty(timer.key))
            {
                return _timers.Remove(timer);
            }
            else
            {
                if (_timersDic.ContainsKey(timer.key))
                {
                    return _timersDic.Remove(timer.key);
                }
            }
            return false;
        }

        internal void PauseOrResumeAll(bool isPause)
        {
            this._isAllPause = isPause;
        }


        internal Timer GetTimer(string key)
        {
            if (!string.IsNullOrEmpty(key) && _timersDic.ContainsKey(key))
            {
                return _timersDic[key];
            }
            return null;
        }
    }
}
